<template>
  <n-spin :show="state.loadingFlag">
    <n-form
      ref="$form"
      :model="model"
      label-placement="left"
      label-align="right"
      :label-width="100"
      require-mark-placement="left"
    >
      <n-form-item
        label="任务名称"
        path="teskName"
        :rule="[{ required: true, message: '请输入任务名称' }]"
      >
        <n-input
          v-model:value="model.teskName"
          clearable
          :maxlength="30"
          :disabled="state.action === 'view' || state.type === 'person'"
        />
      </n-form-item>
      <n-form-item v-if="state.type === 'person'" label="上级任务" path="tesklowerName" required>
        <n-input
          :value="model.tesklowerName || '顶级模块'"
          clearable
          :maxlength="30"
          :disabled="true"
        />
      </n-form-item>
      <n-form-item
        v-else
        label="上级任务"
        path="parentId"
        :rule="[{ required: true, message: '请选择上级任务' }]"
      >
        <n-cascader
          :value="model.parentId"
          :options="state.moduleTree"
          clearable
          filterable
          value-field="id"
          label-field="teskName"
          :disabled="['view', 'edit'].includes(state.action) || state.lockParent"
          @update:value="methods.changeParent"
        />
      </n-form-item>
      <n-form-item label="任务执行" path="projectTaskExeDto">
        <Executor
          v-model="model.projectTaskExeDto"
          :type="state.type"
          :action="state.action"
          :tongan="model.tongan"
          :project-id="projectId"
          :is-lock="isLock"
          :scene="scene"
        />
      </n-form-item>
      <n-flex justify="end">
        <n-button @click="emits('hide')">取消</n-button>
        <n-button
          color="#0A56D8FF"
          :disabled="state.action === 'view'"
          :loading="state.submitFlag"
          @click="(e) => methods.onValidate(e, false)"
        >
          提交
        </n-button>
        <n-button
          v-if="state.type === 'module' && state.action === 'add'"
          color="#0A56D8FF"
          :disabled="state.action === 'view'"
          :loading="state.submitFlag"
          @click="(e) => methods.onValidate(e, true)"
        >
          提交后继续添加
        </n-button>
      </n-flex>
    </n-form>
    <div
      v-if="state.type === 'person' && ['view', 'edit'].includes(state.action) && isLock"
      class="mx-auto mt-20 w-50% flex-col gap-20"
    >
      <n-button
        type="primary"
        :disabled="model.whetherorNot || state.action === 'view'"
        @click="methods.handleApply(0)"
      >
        申请任务排期变更
      </n-button>
      <n-button
        type="primary"
        :disabled="model.whetherorNot || state.action === 'view'"
        @click="methods.handleApply(1)"
      >
        申请任务工期变更
      </n-button>
      <MyModal
        ref="$formAudit"
        :model-form="modelAudit"
        :disabled="type === 'view'"
        @submit="handleSubmit"
      >
        <n-form-item
          label="任务名称"
          path="teskName"
          :rule="[{ required: true, message: '请输入任务名称' }]"
        >
          <n-input v-model:value="modelAudit.teskName" clearable :maxlength="50" :disabled="true" />
        </n-form-item>
        <n-form-item label="上级任务" path="tesklowerName" required>
          <n-input
            v-model:value="modelAudit.tesklowerName"
            clearable
            :maxlength="50"
            :disabled="true"
          />
        </n-form-item>
        <n-form-item
          label="排期"
          path="actualDuration"
          :rule="[{ required: true, message: '请输入排期！' }]"
        >
          <n-input-number
            v-model:value="modelAudit.actualDuration"
            :min="0"
            :max="1000"
            clearable
            :disabled="modelAudit.applicationType === 0"
            @update:value="methods.onChangeDuration"
          />
        </n-form-item>
        <n-form-item
          label="时间范围"
          path="timeRange"
          :rule="[{ required: true, message: '请选择时间范围！' }]"
        >
          <n-date-picker
            v-model:formatted-value="modelAudit.timeRange"
            type="datetimerange"
            value-format="yyyy-MM-dd HH:mm:ss"
            format="yyyy-MM-dd HH:mm"
            :time-picker-props="{ format: 'HH:mm' }"
            :default-time="['09:00:00', '18:30:00']"
            clearable
            start-placeholder="开始时间"
            end-placeholder="结束时间"
            :disabled="modelAudit.applicationType === 1"
            @update:value="methods.onChangeRange"
          />
        </n-form-item>
        <n-form-item
          label="申请原因"
          path="applicationReason"
          :rule="[{ required: true, message: '请选择申请原因！' }]"
        >
          <n-input
            v-model:value="modelAudit.applicationReason"
            clearable
            :maxlength="300"
            show-count
            type="textarea"
            :autosize="{
              minRows: 3,
            }"
          />
        </n-form-item>
      </MyModal>
    </div>
  </n-spin>
</template>
<script setup lang="jsx">
import dayjs from 'dayjs'
import { useWorkday } from '@/hooks/useWorkday'
import _ from 'lodash-es'
import * as auditApi from '@/api/audit'
import { useCrudPro } from '@/hooks/useCrudPro'
import * as taskProjectApi from '@/api/taskProject'
import { objectMergLeft } from '@/utils/common'
import { useUserStore } from '@/store'
defineOptions({ name: 'TaskForm' })
const props = defineProps({
  projectId: {
    type: String,
    default: '',
  },
  exeId: {
    type: String,
    default: '',
  },
  isLock: {
    type: Boolean,
    default: false,
  },
  scene: {
    type: String,
    default: 'all',
  },
})
const emits = defineEmits(['hide', 'reset'])
const userStore = useUserStore()
const { isAllWorkday, getRealDuration } = useWorkday(true)
const $form = ref(null)
function generateModel() {
  return {
    id: null,
    teskName: null,
    tesklowerName: null,
    parentId: null,
    level: null,
    projectTaskExeDto: [],
    tongan: false,
    whetherorNot: false,
  }
}
const model = ref(generateModel())
const state = reactive({
  loadingFlag: false,
  submitFlag: false,
  moduleTree: [],
  // person|module
  type: 'module',
  // view add edit delete
  action: 'add',
  lockParent: false,
})
const methods = reactive({
  async getModuleTree() {
    const { data } = await taskProjectApi.moduleTree({ projectId: props.projectId })
    state.moduleTree = [data]
  },
  onValidate(e, isContinue) {
    e.preventDefault()
    $form.value.validate((errors) => {
      if (!errors) {
        state.submitFlag = true
        const { projectTaskExeDto, ...other } = model.value
        other['projectTaskExeDto'] = projectTaskExeDto.map(({ timeRange, ...info }) => {
          if (timeRange?.length === 2) {
            const [startTime, endTime] = timeRange
            info.startTime = startTime
            info.endTime = endTime
            info.actualDuration = getRealDuration(startTime, endTime)
          }
          return info
        })
        if (state.type === 'module' && state.action === 'add') {
          taskProjectApi
            .addModule({ ...other, projectId: props.projectId })
            .then(() => {
              $message.success('添加任务成功！')
              if (isContinue) {
                model.value = generateModel()
                this.getModuleTree()
                emits('reset')
              } else {
                emits('hide')
                emits('reset')
              }
            })
            .finally(() => {
              state.submitFlag = false
            })
        } else if (state.type === 'module' && state.action === 'edit') {
          taskProjectApi
            .editModule({ ...other, projectId: props.projectId })
            .then(() => {
              $message.success('修改任务成功！')
              emits('hide')
              emits('reset')
            })
            .finally(() => {
              state.submitFlag = false
            })
        } else if (state.type === 'person' && state.action === 'edit') {
          taskProjectApi
            .editPerson(other['projectTaskExeDto'][0])
            .then(() => {
              $message.success('修改任务执行成功！')
              emits('hide')
              emits('reset')
            })
            .finally(() => {
              state.submitFlag = false
            })
        }
      }
    })
  },
  // type: person|module, action: view add edit delete
  async initModel(type, action, params = {}) {
    const { id, parentId = null, level = null } = params
    state.type = type
    state.action = action
    state.lockParent = false
    if (type === 'module' && ['view', 'edit'].includes(action)) {
      state.loadingFlag = true
      let { data } = await taskProjectApi.infoModule(id)
      data['projectTaskExeDto'] = (data['projectTaskExeDto'] || []).map((item) => {
        if (item.startTime && item.endTime) {
          item.timeRange = [item.startTime, item.endTime]
        }
        return item
      })
      model.value = objectMergLeft(model.value, data)
      state.loadingFlag = false
    } else if (type === 'person' && ['view', 'edit'].includes(action)) {
      state.loadingFlag = true
      let { data } = await taskProjectApi.infoPerson(id)
      if (data.startTime && data.endTime) {
        data.timeRange = [data.startTime, data.endTime]
      }
      const value = {
        teskName: data.teskName,
        tesklowerName: data.tesklowerName,
        whetherorNot: data.whetherorNot,
        projectTaskExeDto: [data],
      }
      model.value = objectMergLeft(model.value, value)
      state.loadingFlag = false
    } else if (type === 'module' && action === 'add' && parentId) {
      model.value.parentId = parentId
      model.value.level = level + 1
      state.lockParent = true
    }
  },
  changeParent(id, item) {
    if (id && item) {
      model.value.parentId = id
      model.value.level = item.level + 1
    } else {
      model.value.parentId = null
      model.value.level = null
    }
  },
  handleApply(applicationType) {
    handleEdit({ ..._.cloneDeep(model.value['projectTaskExeDto'][0]), applicationType }, () => {
      $formAudit.value.setState(
        'title',
        applicationType === 0 ? '申请任务排期变更' : '申请任务工期变更'
      )
    })
  },
  onChangeDuration(duration) {
    const [startTime] = modelAudit.value.timeRange
    // console.log(duration, startTime)
    let endTime = startTime
    while (duration > 0) {
      endTime = dayjs(endTime).add(1, 'day').format('YYYY-MM-DD 00:00:00')
      if (isAllWorkday(endTime)) {
        duration--
      }
    }
    // console.log(endTime)
    modelAudit.value.timeRange[1] = endTime
  },
  onChangeRange(_, range) {
    modelAudit.value.actualDuration = getRealDuration(...range)
  },
})
const {
  type,
  model: modelAudit,
  $form: $formAudit,
  handleEdit,
  handleSubmit,
} = useCrudPro({
  initForm: {
    teskName: null,
    tesklowerName: null,
    actualDuration: null,
    timeRange: null,
    applicationReason: null,
    applicationType: null,
  },
  apis: {
    edit: auditApi.add,
  },
  formatParams(params) {
    // console.log(params)
    const { applicationType, timeRange, actualDuration, applicationReason } = params
    let beforeApplication = null
    let afterApplication = null
    let daysorTimerange = null
    if (applicationType === 0) {
      beforeApplication = model.value['projectTaskExeDto'][0].timeRange.join(' 至 ')
      afterApplication = timeRange.join(' 至 ')
      daysorTimerange = `${actualDuration}`
    } else if (applicationType === 1) {
      beforeApplication = model.value['projectTaskExeDto'][0].actualDuration
      afterApplication = actualDuration
      daysorTimerange = timeRange.join(' 至 ')
    }
    const result = {
      applicationType,
      projectId: props.projectId,
      projectExeId: props.exeId,
      applicant: userStore.userId,
      beforeApplication,
      afterApplication,
      applicationReason,
      daysorTimerange,
    }
    // console.log(result)
    return result
  },
  handleChange() {
    $message.success('提交成功')
    userStore.getUnauditedCount()
    model.value.whetherorNot = true
  },
})
onBeforeMount(() => {
  methods.getModuleTree()
})
watch(
  () => props.projectId,
  (val) => {
    val && methods.getModuleTree()
  }
)
defineExpose({
  initModel: methods.initModel,
})
</script>
<style lang="scss" scoped></style>
